﻿using System;
using System.Data.Common;
using System.Windows.Forms;
using SSAT.Commands;

namespace SSAT.Utils
{
    /// <summary>
    /// Contains methods to simplify some common deals with the UI controls.
    /// </summary>
    internal static class UIHelper
    {
        private static void GeneralToolStripMenuItemClickHandler(object sender, EventArgs e)
        {
            ToolStripItem menuItem = sender as ToolStripItem;
            if (menuItem == null)
            {
                return;
            }
            CommandBase command = menuItem.Tag as CommandBase;
            if (command != null)
            {
                command.Execute();
            }
        }

        /// <summary>
        /// Assigns command to the specified menu (context) strip item. If the command has DisplayName then
        /// this name will be displayed in the item as text, otherwise item will have the same text. It is 
        /// strongly recomended to use UnregisterToolStripMenuClickHandler to remove command, to avoid
        /// memory leaks.
        /// </summary>
        /// <param name="menuItem">Owner of this command.</param>
        /// <param name="command">Command instance to assign.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static void RegisterToolStripMenuClickHandler(ToolStripItem menuItem, CommandBase command)
        {
            Verification.CheckArgumentForNull(menuItem, "menuItem");
            Verification.CheckArgumentForNull(command, "command");
            menuItem.Tag = command;
            if (!string.IsNullOrEmpty(command.DisplayName))
            {
                menuItem.Text = command.DisplayName;
            }
            menuItem.Click += GeneralToolStripMenuItemClickHandler;
            command.AddDependentControl(menuItem);
        }

        /// <summary>
        /// Removes click event handler and command from the specified menu (context) strip item.
        /// </summary>
        /// <param name="menuItem">Item with click event to remove.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static void UnregisterToolStripMenuClickHandler(ToolStripItem menuItem)
        {
            Verification.CheckArgumentForNull(menuItem, "menuItem");
            menuItem.Click -= GeneralToolStripMenuItemClickHandler;
            menuItem.Tag = null;
        }

        public static void ShowErrorDialog(string message)
        {
            MessageBox.Show(message, Resources.ErrorInTheApplication, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        public static void ShowErrorDialog(Exception error)
        {
            ShowExceptionOccuredDialog(error, Resources.WeAreSorryButThereFollowingErrorOccured);
        }

        public static void ShowConnectionErrorDialog(DbException error)
        {
            ShowExceptionOccuredDialog(error, Resources.ErrorOccuredDuringOpeningConnectionWithMessage);
        }

        /// <param name="format">Format string with {0}.</param>
        private static void ShowExceptionOccuredDialog(Exception error, string format)
        {
            Verification.CheckArgumentForNull(error, "error");
            ShowErrorDialog(string.Format(format, error.Message));
        }

        /// <summary>
        /// To change properties or call methods in the Windows controls in 
        /// thread-safe fashion use this method.
        /// </summary>
        /// <param name="control">Control to invoke.</param>
        /// <param name="method">Method which uses properties or methods of the control.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static void InvokeSafely(Control control, Action method)
        {
            Verification.CheckArgumentForNull(control, "control");
            Verification.CheckArgumentForNull(method, "method");
            if (control.InvokeRequired)
            {
                control.Invoke(method);
            }
            else
            {
                method.Invoke();
            }
        }
    }
}
